﻿///Code based on
/// http://snipd.net/minimax-algorithm-with-alpha-beta-pruning-in-c

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using Core.Models;
using Core.Models.Enums;

namespace Service.AI
{
    public class Node
    {
        public GameState gs;
        private Node bestNode;
        private ChessPieceColor currentPlayer;
        public MovesInfo currentMi { get; set; }
        public MovesInfo ogMove { get; set; }

        public bool isAttacking { get; set; }

        public Node(GameState p_Gs)
        {
            isAttacking = false;
            gs = p_Gs;
            currentMi = new MovesInfo();
            currentPlayer = gs.WhoseMove;
        }

        public Node(GameState p_Gs, MovesInfo mi, MovesInfo p_ogMove)
        {
            isAttacking = false;
            gs = p_Gs;
            ogMove = p_ogMove;
            if (mi != null)
            {
                if (gs.MovePiece((byte) mi.SourceColumn, (byte) mi.SourceRow, (byte) mi.DestColumn,(byte) mi.DestRow))
                {
                    currentMi = mi;
                }
                else
                {
                    currentMi = null;
                }
            }
            currentPlayer = gs.WhoseMove;
        }

        public Node(GameState p_Gs, MovesInfo mi, MovesInfo p_ogMove, bool p_IsAttacking)
        {
            isAttacking = p_IsAttacking;
            gs = p_Gs;
            ogMove = p_ogMove;
            if (mi != null)
            {
                if (gs.MovePiece((byte)mi.SourceColumn, (byte)mi.SourceRow, (byte)mi.DestColumn, (byte)mi.DestRow))
                {
                    currentMi = mi;
                }
                else
                {
                    currentMi = null;
                }
            }
            currentPlayer = gs.WhoseMove;
        }


        public List<Node> Children()
        {
            if (currentMi != null )
            {
                List<Node> children = new List<Node>();
                try
                {
                    List<MovesInfo> listMoves = gs.GetBoardMoves();
                    for (int i = 0; i < listMoves.Count; i++)
                    {
                        bool newIsAtk = false;
                        if (gs.GetPieceTypeAt((byte)listMoves[i].DestColumn, (byte)listMoves[i].DestRow) != ChessPieceType.None)
                        {
                            if (gs.GetPieceColorAt((byte) listMoves[i].DestColumn, (byte) listMoves[i].DestRow) != gs.WhoseMove)
                                newIsAtk = true;
                        }

                        if (ogMove == null)
                        {
                            GameState newGs = new GameState(gs.GetBoardFen(true));
                            newGs.WhoseMove = currentPlayer;
                            children.Add(new Node(newGs, listMoves[i], listMoves[i],newIsAtk));
                        }
                        else
                        {
                            GameState newGs = new GameState(gs.GetBoardFen(true));
                            newGs.WhoseMove = currentPlayer;
                            children.Add(new Node(newGs, listMoves[i], ogMove,newIsAtk));
                        }
                    }
                }
                catch (Exception ex)
                {
                    Debug.Write(ex.StackTrace);
                }
                
                // Create your subtree here and return the results
                var childrenList = children.Where(c => c.currentMi != null).OrderByDescending(c => c.isAttacking).ToList();
                //var childrenList = children.Where(c => c.currentMi != null).ToList();

                return childrenList;
            }

            return null;
        }
    }
}